home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Friends / Wave / WavesWorld / Source / IBPalettes / WW3DKit / RIBCommand.m < prev    next >
Encoding:
Text File  |  1995-03-22  |  34.8 KB  |  1,076 lines

  1. // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
  2. // see COPYRIGHT for reuse legalities
  3. //
  4.  
  5. #import "RIBCommand.h"
  6. #import "WWEveParser.h"  // for the WW_ defines...
  7. #import "WWSceneClock.h"
  8. #import "WW3DAttributeState.h"
  9. #import <stdio.h>
  10.  
  11. @implementation RIBCommand
  12.  
  13. + initialize { return [RIBCommand setVersion:1], self; }
  14.  
  15. - init
  16. {
  17.   [super init];
  18.  
  19.   n = 0;
  20.   tokens = (RtToken *)NULL;
  21.   parms = (RtPointer *)NULL;
  22.   archiveVector = (char **)NULL;
  23.   printfNVector = (int *)NULL;
  24.   printfTypeVector = (int *)NULL;
  25.  
  26.   dirtyBoundingBox = TRUE;
  27.  
  28.   return self;
  29. }
  30.  
  31.  
  32. - awake
  33. {
  34.   [super awake];
  35.  
  36.   dirtyBoundingBox = TRUE;
  37.  
  38.   return self;
  39. }
  40.  
  41.  
  42. - (void)setN:(int)newN tokens:(RtToken *)newTokens parms:(RtPointer *)newParms archiveVector:(char **)newArchiveVector printfTypeVector:(int *)newPrintfTypeVector printfNVector:(int *)newPrintfNVector
  43. {  
  44.    int  i;
  45.  
  46.  
  47.    if (n)
  48.    {  for (i = 0; i < n; i++)
  49.       {  // don't free the tokens; they're shared!
  50.          free(parms[i]);
  51.          free(archiveVector[i]);
  52.          free(printfNVector);
  53.          free(printfTypeVector);
  54.       }
  55.       if (newN > n)
  56.       {  tokens = (RtToken *)NXZoneRealloc([self zone], tokens, (newN * sizeof(RtToken)));
  57.          parms = (RtPointer *)NXZoneRealloc([self zone], parms, (newN * sizeof(RtPointer)));
  58.          archiveVector = (char **)NXZoneRealloc([self zone], archiveVector, (newN * sizeof(archiveVector)));
  59.          printfNVector = (int *)NXZoneRealloc([self zone], printfNVector, (newN * sizeof(int)));
  60.          printfTypeVector = (int *)NXZoneRealloc([self zone], printfTypeVector, (newN * sizeof(int)));
  61.       }
  62.    }
  63.    else
  64.    {  tokens = (RtToken *)NXZoneMalloc([self zone], newN * sizeof(RtToken));
  65.       parms = (RtPointer *)NXZoneMalloc([self zone], newN * sizeof(RtPointer));
  66.       archiveVector = (char **)NXZoneMalloc([self zone], newN * sizeof(archiveVector));
  67.       printfNVector = (int *)NXZoneMalloc([self zone], newN * sizeof(int));
  68.       printfTypeVector = (int *)NXZoneMalloc([self zone], newN * sizeof(int));
  69.    }
  70.    n = newN;
  71.    for (i = 0; i < n; i++)
  72.    {  tokens[i] = newTokens[i];
  73.       parms[i] = newParms[i];
  74.       archiveVector[i] = newArchiveVector[i];
  75.       printfNVector[i] = newPrintfNVector[i];
  76.       printfTypeVector[i] = newPrintfTypeVector[i];
  77.    }
  78.  
  79.    dirtyBoundingBox = TRUE;
  80.    return ;
  81. }
  82.  
  83. - free
  84. {
  85.   int i;
  86.  
  87.  
  88.   //NXLogError("%s %d being free'ed\n", [[self class] name], self);
  89.   // don't free the tokens; they're constants (i.e. RI_P, RI_PW, etc.)
  90.   //NXLogError("RIBCommand %s: freeing %p", [[self class] name], self);
  91.   for (i = 0; i < n; i++)
  92.   {  if (parms[i]) { free(parms[i]); }
  93.      if (archiveVector[i]) { free(archiveVector[i]); }
  94.   }
  95.   if (n)  
  96.   {  if (printfNVector) { free(printfNVector); }
  97.      if (printfTypeVector) { free(printfTypeVector); }
  98.   }
  99.   return [super free];
  100. }
  101.  
  102. // this should only be called internally
  103. // the receiving object needs to copy all the parameters using the passed in zone
  104. // the assumption is that 
  105. - _mallocPointersUsingZone:(NXZone *)zone
  106. {
  107.    if (n)
  108.    {  tokens = (RtToken *)NXZoneMalloc([self zone], n * sizeof(RtToken));
  109.       if (!tokens)
  110.       {  return nil;
  111.       }
  112.       parms = (RtPointer *)NXZoneMalloc([self zone], n * sizeof(RtPointer));
  113.       if (!parms)
  114.       {  NXZoneFree(zone, tokens);
  115.          return nil;
  116.       }
  117.       archiveVector = (char **)NXZoneMalloc([self zone], n * sizeof(char *));
  118.       if (!archiveVector)
  119.       {  NXZoneFree(zone, tokens);
  120.          NXZoneFree(zone, parms);
  121.          return nil;
  122.       }
  123.       printfNVector = (int *)NXZoneMalloc([self zone], n * sizeof(int));
  124.       if (!printfNVector)
  125.       {  NXZoneFree(zone, tokens);
  126.          NXZoneFree(zone, parms);
  127.          NXZoneFree(zone, archiveVector);
  128.          return nil;
  129.       }
  130.       printfTypeVector = (int *)NXZoneMalloc([self zone], n * sizeof(int));
  131.       if (!printfTypeVector)
  132.       {  NXZoneFree(zone, tokens);
  133.          NXZoneFree(zone, parms);
  134.          NXZoneFree(zone, archiveVector);
  135.          NXZoneFree(zone, printfNVector);
  136.          return nil;
  137.       }
  138.    }
  139.    else
  140.    {  // n == 0
  141.       tokens = (RtToken *)NULL;
  142.       parms = (RtPointer *)NULL;
  143.       archiveVector = (char **)NULL;
  144.       printfNVector = (int *)NULL;
  145.       printfTypeVector = (int *)NULL;
  146.    }
  147.    return self;
  148. }
  149.  
  150. - _setToken:(char *)newToken parm:(RtPointer)newParm i:(int)i archiveInfo:(char *)archiveInfo type:(int)parmType count:(int)howMany usingZone:(NXZone *)zone
  151. {
  152.    int  j;
  153.  
  154.  
  155.    tokens[i] = (RtToken)NXZoneMalloc(zone, (1 + strlen(newToken)));
  156.    if (!tokens[i])
  157.    {  return nil;
  158.    }
  159.    strcpy(tokens[i], newToken);
  160.  
  161.    archiveVector[i] = (char *)NXZoneMalloc(zone, (1 + strlen(archiveInfo)));
  162.    if (!archiveVector[i])
  163.    {  NXZoneFree(zone, tokens[i]);
  164.       return nil;
  165.    }
  166.    strcpy(archiveVector[i], archiveInfo);
  167.  
  168.    printfTypeVector[i] = parmType;
  169.    printfNVector[i] = howMany;
  170.  
  171.    // in a perfect world, I could just copy that chunk o memory over,
  172.    // but I'm worried about alignment problems, so I'll do it the slow way...
  173.    switch (printfTypeVector[i])
  174.    {  case WW_FLOAT:  parms[i] = (RtFloat *)NXZoneMalloc(zone, sizeof(RtFloat) * howMany); 
  175.                       for (j = 0; j < printfNVector[i]; j++)
  176.               {  *((RtFloat *)parms[i] + j) = *((RtFloat *)(newParm) + j);
  177.               }
  178.                       break;
  179.       case WW_COLOR:  parms[i] = (RtFloat *)NXZoneMalloc(zone, sizeof(RtFloat) * howMany); 
  180.                       for (j = 0; j < printfNVector[i]; j++)
  181.               {  *((RtFloat *)parms[i] + j) = *((RtFloat *)(newParm) + j);
  182.               }
  183.                       break;
  184.       case WW_POINT:  parms[i] = (RtFloat *)NXZoneMalloc(zone, sizeof(RtFloat) * howMany); 
  185.                       for (j = 0; j < printfNVector[i]; j++)
  186.               {  *((RtFloat *)parms[i] + j) = *((RtFloat *)(newParm) + j);
  187.               }
  188.                       break;
  189.       case WW_INT:    parms[i] = (int *)NXZoneMalloc(zone, sizeof(int) * howMany); 
  190.                       for (j = 0; j < printfNVector[i]; j++)
  191.               {  *((int *)parms[i] + j) = *((int *)(newParm) + j);
  192.               }
  193.                       break;
  194.       // hmm, strings are weirder.  
  195.       case WW_STRING: parms[i] = (char **)NXZoneMalloc(zone, sizeof(char *) * howMany); 
  196.                       for (j = 0; j < printfNVector[i]; j++)
  197.               {  // need to additionally malloc up some memory here, folks
  198.                          *((char **)parms[i] + j) = (char *)NXZoneMalloc(zone, (1 + strlen(*((char **)(newParm) + j))));
  199.                          strcpy(*((char **)parms[i] + j), *((char **)(newParm) + j));
  200.               }
  201.                       break;
  202.    }      
  203.    return self;
  204. }
  205.  
  206.  
  207. - copyFromZone:(NXZone *)zone
  208. {
  209.   int  i;
  210.   id   newCopy = [super copyFromZone:zone];
  211.  
  212.   // now we need to grovel over the parameters and copy them 
  213.   // this is a pain, but boy, will it be cool...
  214.   // okay, malloc up the base list of pointers
  215.   [newCopy _mallocPointersUsingZone:zone];
  216.   for (i = 0; i < n; i++)
  217.   {  if (![newCopy _setToken:tokens[i] parm:parms[i] i:i 
  218.                        archiveInfo:archiveVector[i] type:printfTypeVector[i] count:printfNVector[i] 
  219.                        usingZone:zone])
  220.      {  [newCopy free];
  221.         return nil;
  222.      }
  223.   }
  224.   
  225.   return newCopy;
  226. }
  227.  
  228. - _lerpParametersWith:b by:(float)u
  229. {
  230.   int        i, j;
  231.   RtToken    *tokensB;
  232.   char       **archiveVectorB;
  233.   int        *printfNVectorB;
  234.   int        *printfTypeVectorB;
  235.   RtPointer  *parmsB;
  236.  
  237.  
  238.   // okay, first thing to realize is that this instance already has its 
  239.   // parameters set to the (u ==0) case here.  Therefore, when in doubt, 
  240.   // you can leave it alone and you're fine.  We now want to grovel 
  241.   // over the two objects' parameters.  
  242.   if (n != [b n])
  243.   { // hmm.  looks like trouble.  At some point, we'll have to bail,
  244.     // since the parameter lists aren't the same length.  we could
  245.     // bail right away, since we know that "self"'s parameters are set
  246.     // to something reasonable...  Yea, let's bail.
  247.     return self;
  248.   }
  249.  
  250.   tokensB = [b tokens];
  251.   archiveVectorB = [b archiveVector];
  252.   printfNVectorB = [b printfNVector];
  253.   printfTypeVectorB = [b printfTypeVector];
  254.   parmsB = [b parms];
  255.  
  256.   // okay, at this point, we know that these two objects are the same 
  257.   // class, and the length of their parameter lists are the same. Of
  258.   // course, this might be just a lucky coincidence, and the actual 
  259.   // parameters might be different types.  
  260.  
  261.   for (i = 0; i < n; i++)
  262.   {  if ((tokens[i] == tokensB[i]) || (!strcmp(tokens[i], tokensB[i])))
  263.      {  // great! they're the same token.
  264.         // now we need to make sure they're the same type and length of data
  265.         // if not, bail to the next parameter
  266.         if ((printfNVector[i] == printfNVectorB[i]) && (printfTypeVector[i] == printfTypeVectorB[i]))
  267.     {  // okay! we're golden. Let's do a lerp...
  268.            switch (printfTypeVector[i])
  269.            {  case WW_FLOAT:   for (j = 0; j < printfNVector[i]; j++)
  270.                        {  *((RtFloat *)parms[i] + j) += ((*((RtFloat *)(parmsB[i]) + j) - *((RtFloat *)parms[i] + j)) * u);
  271.                        }
  272.                                break;
  273.               case WW_COLOR:   for (j = 0; j < printfNVector[i]; j++)
  274.                        {  *((RtFloat *)parms[i] + j) += ((*((RtFloat *)(parmsB[i]) + j) - *((RtFloat *)parms[i] + j)) * u);
  275.                        }
  276.                                break;
  277.               case WW_POINT:   for (j = 0; j < printfNVector[i]; j++)
  278.                        {  *((RtFloat *)parms[i] + j) += ((*((RtFloat *)(parmsB[i]) + j) - *((RtFloat *)parms[i] + j)) * u);
  279.                        }
  280.                                break;
  281.               case WW_INT:     for (j = 0; j < printfNVector[i]; j++)
  282.                        {  *((int *)parms[i] + j) += ((*((int *)(parmsB[i]) + j) - *((int *)parms[i] + j)) * u);
  283.                    }
  284.                                break;
  285.               case WW_STRING:  // can't lerp strings without more info...
  286.                                // maybe could encode a way to do it with enumerated values, but for now, bail...
  287.                                break;
  288.            }
  289.         }
  290.         else
  291.         {  // okay, that parameter can't be lerp'ed; on to the next
  292.         }
  293.      }
  294.      else
  295.      {  // okay, that parameter can't be lerp'ed; on to the next
  296.      }
  297.   }
  298.  
  299.   
  300.  
  301.   return self;
  302. }
  303.  
  304.  
  305. // note: because we've made the WWSampleList "safe" for having
  306. // multiple samples with the same data, it's perfectly valid to return
  307. // yourself or b
  308. - lerpWith:b by:(float)uValue
  309. {
  310.    id  newMe = nil;
  311.  
  312.  
  313.    if (([self class] != [b class]) || (uValue <= 0.0))
  314.    {  return self;
  315.    }
  316.  
  317.    if (uValue >= 1.0)
  318.    {  return b;
  319.    }
  320.  
  321.    newMe = [self copyFromZone:[self zone]];
  322.  
  323.    // okay, now we have to get newMe to linearly interpolate it
  324.    // parameters partway between "self" and "b"
  325.    [newMe _lerpParametersWith:b by:uValue];
  326.  
  327.    return newMe;
  328. }
  329.  
  330. - lerpSelfWith:b by:(float)uValue
  331. {
  332.    if (([self class] != [b class]) || (uValue <= 0.0))
  333.    {  return self;
  334.    }
  335.  
  336.    if (uValue >= 1.0)
  337.    {  return b;
  338.    }
  339.  
  340.    // okay, now we have to get newMe to linearly interpolate it
  341.    // parameters partway between "self" and "b"
  342.    [self _lerpParametersWith:b by:uValue];
  343.  
  344.    return self;
  345. }
  346.  
  347. - (BOOL)pushesOrPopsCTM { return NO; }
  348. - (BOOL)pushesCTM { return NO; }
  349. - (BOOL)popsCTM { return NO; }
  350.  
  351. - (BOOL)hasBoundingBox { return NO; }
  352.  
  353. - (float)lastSampleIsAt { return 0.0; }
  354.  
  355. - (unsigned long int)maxSampleBandwidth  
  356. {  
  357.    unsigned long int maxSampleBandwidth = 0;
  358.    int  i, j;
  359.  
  360.   
  361.    if (!n)
  362.    {  return maxSampleBandwidth;
  363.    }
  364.    for (i = 0; i < n; i++)
  365.    {  maxSampleBandwidth += 1 + strlen(tokens[i]);
  366.       switch (printfTypeVector[i])
  367.       {  case WW_FLOAT:   maxSampleBandwidth += (printfNVector[i] * sizeof(RtFloat));
  368.                           break;
  369.          case WW_COLOR:   maxSampleBandwidth += (printfNVector[i] * sizeof(RtFloat));
  370.                           break;
  371.          case WW_POINT:   maxSampleBandwidth += (printfNVector[i] * sizeof(RtFloat));
  372.                           break;
  373.          case WW_INT:     maxSampleBandwidth += (printfNVector[i] * sizeof(long));
  374.                           break;
  375.          case WW_STRING:  for (j = 0; j < printfNVector[i]; j++)
  376.                        {  maxSampleBandwidth += 1 + strlen(*((char **)(parms[i]) + j));
  377.               }
  378.                           break;
  379.       }      
  380.    }
  381.    return maxSampleBandwidth;
  382. }
  383.  
  384. - deriveHowManyPoints:(char *)archiveStr ofLength:(int)divisor
  385. {
  386.   char howManyStr[32];
  387.  
  388.  
  389.   // the string looks like "[1234f]"
  390.   strcpy(howManyStr, (archiveStr + 1));
  391.   howManyStr[strlen(howManyStr) - 2] = '\0';
  392.   howManyPoints = atoi(howManyStr) / divisor;
  393.  
  394.   return self;
  395. }
  396.  
  397. - (BOOL)isMoot  {  return NO;  }
  398. - (BOOL)isMootStartingAt:(float)startTime endingAt:(float)endTime  {  return [self isMoot];  }
  399.  
  400. // this routine, on the other hand, should be called by subclasses implementing -theSameAs:
  401. - (BOOL)theSameAs:otherRIBCommand
  402. {
  403.   int  i, j;
  404.   RtToken    *tokens2;
  405.   RtPointer  *parms2;
  406.   int        *printfNVector2;
  407.   int        *printfTypeVector2;
  408.  
  409.   
  410.   if ([self class] != [otherRIBCommand class])
  411.   {  return NO;
  412.   }
  413.  
  414.   if (n != [otherRIBCommand n])
  415.   {  return NO;
  416.   }
  417.  
  418.   tokens2 = [otherRIBCommand tokens];
  419.   parms2 = [otherRIBCommand parms];
  420.   printfNVector2 = [otherRIBCommand printfNVector];
  421.   printfTypeVector2 = [otherRIBCommand printfTypeVector];
  422.  
  423.   // note that there is a false (but probably okay) assumption here
  424.   // that the parameters are in the same order.  This doesn't have to be
  425.   // true, but for my stuff, probably will be true.
  426.   for (i = 0; i < n; i++)
  427.   {  if (tokens[i] != tokens2[i])
  428.      {  if (strcmp(tokens[i], tokens2[i]))
  429.         {  return NO;
  430.         }
  431.      }
  432.  
  433.      switch (printfTypeVector[i])
  434.      {  case WW_FLOAT:   if (printfNVector[i] != printfNVector2[i])
  435.                          {  return NO;
  436.                          }
  437.                          for (j = 0; j < printfNVector[i]; j++)
  438.                      {  if (*((RtFloat *)(parms[i]) + j) != *((RtFloat *)(parms2[i]) + j))
  439.                 return NO;
  440.              }
  441.                          break;
  442.         case WW_COLOR:   if (printfNVector[i] != printfNVector2[i])
  443.                          {  return NO;
  444.                          }
  445.                          for (j = 0; j < printfNVector[i]; j++)
  446.                      {  if (*((RtFloat *)(parms[i]) + j) != *((RtFloat *)(parms2[i]) + j))
  447.                 return NO;
  448.              }
  449.                          break;
  450.         case WW_POINT:   if (printfNVector[i] != printfNVector2[i])
  451.                          {  return NO;
  452.                          }
  453.                          for (j = 0; j < printfNVector[i]; j++)
  454.                      {  if (*((RtFloat *)(parms[i]) + j) != *((RtFloat *)(parms2[i]) + j))
  455.                 return NO;
  456.              }
  457.                          break;
  458.         case WW_INT:   if (printfNVector[i] != printfNVector2[i])
  459.                          {  return NO;
  460.                          }
  461.                          for (j = 0; j < printfNVector[i]; j++)
  462.                      {  if (*((RtInt *)(parms[i]) + j) != *((RtInt *)(parms2[i]) + j))
  463.                 return NO;
  464.              }
  465.                          break;
  466.         case WW_STRING:   if (printfNVector[i] != printfNVector2[i])
  467.                          {  return NO;
  468.                          }
  469.                          for (j = 0; j < printfNVector[i]; j++)
  470.                      {  if (strcmp(*((char **)(parms[i]) + j), *((char **)(parms2[i]) + j)))
  471.                 return NO;
  472.              }
  473.                          break;
  474.      }      
  475.   }
  476.   return YES;
  477. }
  478.  
  479.  
  480.  
  481. - (BOOL)similarTo:otherRIBCommand 
  482. {
  483.   if ([self class] != [otherRIBCommand class])
  484.   {  return NO;
  485.   }
  486.   if (n != [otherRIBCommand n])
  487.   {  return NO;
  488.   }
  489.   return YES;
  490. }
  491.  
  492.  
  493. - calculateBoundingBoxStartingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  494. {
  495.   int      i = 0, j = 1;
  496.   BOOL     notFound = YES;
  497.   RtFloat  *aPointPtr;
  498.  
  499.  
  500.   while (notFound && (i < n))
  501.   {  if (!strcmp(tokens[i], "P"))
  502.      {  notFound = NO;
  503.         aPointPtr = (RtFloat *)(parms[i]);
  504.     boundingBox[0] = aPointPtr[0];
  505.     boundingBox[1] = aPointPtr[0];
  506.     boundingBox[2] = aPointPtr[1];
  507.     boundingBox[3] = aPointPtr[1];
  508.     boundingBox[4] = aPointPtr[2];
  509.     boundingBox[5] = aPointPtr[2];
  510.         if (!howManyPoints)
  511.     {  [self deriveHowManyPoints:archiveVector[i] ofLength:3];
  512.         }
  513.         while (j++ < howManyPoints)
  514.         {  if (aPointPtr[0] < boundingBox[0]) { boundingBox[0] = aPointPtr[0]; }
  515.            if (aPointPtr[0] > boundingBox[1]) { boundingBox[1] = aPointPtr[0]; }
  516.            if (aPointPtr[1] < boundingBox[2]) { boundingBox[2] = aPointPtr[1]; }
  517.            if (aPointPtr[1] > boundingBox[3]) { boundingBox[3] = aPointPtr[1]; }
  518.            if (aPointPtr[2] < boundingBox[4]) { boundingBox[4] = aPointPtr[2]; }
  519.            if (aPointPtr[2] > boundingBox[5]) { boundingBox[5] = aPointPtr[2]; }
  520.            aPointPtr += 3;
  521.         }
  522.      }
  523.      if (!strcmp(tokens[i], "Pz"))
  524.      {  notFound = NO;
  525.         aPointPtr = (RtFloat *)(parms[i]);
  526.     boundingBox[0] = 0.0;
  527.     boundingBox[1] = 1.0;
  528.     boundingBox[2] = 0.0;
  529.     boundingBox[3] = 1.0;
  530.     boundingBox[4] = aPointPtr[0];
  531.     boundingBox[5] = aPointPtr[0];
  532.         if (!howManyPoints)
  533.     {  [self deriveHowManyPoints:archiveVector[i] ofLength:1];
  534.         }
  535.         while (j++ < howManyPoints)
  536.         {  if (aPointPtr[0] < boundingBox[4]) { boundingBox[4] = aPointPtr[0]; }
  537.            if (aPointPtr[0] > boundingBox[5]) { boundingBox[5] = aPointPtr[0]; }
  538.            aPointPtr++;
  539.         }
  540.      }
  541.      if (!strcmp(tokens[i], "Pw"))
  542.      {  notFound = NO;
  543.         aPointPtr = (RtFloat *)(parms[i]);
  544.     boundingBox[0] = ((aPointPtr[0]) / (aPointPtr[3]));
  545.     boundingBox[1] = ((aPointPtr[1]) / (aPointPtr[3]));
  546.     boundingBox[2] = ((aPointPtr[2]) / (aPointPtr[3]));
  547.     boundingBox[3] = ((aPointPtr[0]) / (aPointPtr[3]));
  548.     boundingBox[4] = ((aPointPtr[1]) / (aPointPtr[3]));
  549.     boundingBox[5] = ((aPointPtr[2]) / (aPointPtr[3]));
  550.         if (!howManyPoints)
  551.     {  [self deriveHowManyPoints:archiveVector[i] ofLength:4];
  552.         }
  553.         while (j++ < howManyPoints)
  554.         {  if ((aPointPtr[0]/aPointPtr[3]) < boundingBox[0])
  555.            { boundingBox[0] = (aPointPtr[0]/aPointPtr[3]); 
  556.            }
  557.            if ((aPointPtr[0]/aPointPtr[3]) > boundingBox[1])
  558.            { boundingBox[1] = (aPointPtr[0]/aPointPtr[3]); 
  559.            }
  560.            if ((aPointPtr[1]/aPointPtr[3]) < boundingBox[2])
  561.            { boundingBox[2] = (aPointPtr[1]/aPointPtr[3]); 
  562.            }
  563.            if ((aPointPtr[1]/aPointPtr[3]) > boundingBox[3])
  564.            { boundingBox[3] = (aPointPtr[1]/aPointPtr[3]); 
  565.            }
  566.            if ((aPointPtr[2]/aPointPtr[3]) < boundingBox[4])
  567.            { boundingBox[4] = (aPointPtr[2]/aPointPtr[3]); 
  568.            }
  569.            if ((aPointPtr[2]/aPointPtr[3]) > boundingBox[5])
  570.            { boundingBox[5] = (aPointPtr[2]/aPointPtr[3]); 
  571.            }
  572.            aPointPtr += 4;
  573.         }
  574.      }
  575.      i++;
  576.   }
  577.  
  578.   if (notFound)
  579.   {  NXLogError("unable to find any points token (RI_P, RI_Z, RI_PW) for %s - can't calculate bounding box...", [[self class] name]);
  580.      return nil;
  581.   }
  582.   dirtyBoundingBox = FALSE; 
  583.   return self;
  584. }
  585.  
  586.  
  587. - setBoundingBox:(RtBound *)newBoundingBox
  588. {
  589.   N3D_CopyBound(*newBoundingBox, boundingBox);
  590.  
  591.   return self;
  592. }
  593.  
  594. - getBoundingBox:(RtBound *)boundingBoxContainer
  595. {
  596.   N3D_CopyBound(boundingBox, *boundingBoxContainer);
  597.  
  598.   return self;
  599. }
  600.  
  601. - (RtBound *)boundingBoxStartingAt:(RtFloat)intervalStartTime endingAt:(RtFloat)intervalEndTime
  602.    if (dirtyBoundingBox) 
  603.    {  [self calculateBoundingBoxStartingAt:intervalStartTime endingAt:intervalEndTime];
  604.    }
  605.    return &boundingBox; 
  606. }
  607.  
  608. - setMyShape:shape { myShape = shape;  return self; }
  609.  
  610. - shape { return myShape; }
  611.  
  612. - (int)n { return n; }
  613. - (RtToken *)tokens { return tokens; }
  614. - (RtPointer *)parms { return parms; }
  615. - (char **)archiveVector { return archiveVector; }
  616. - (int *)printfNVector { return printfNVector; }
  617. - (int *)printfTypeVector { return printfTypeVector; }
  618.  
  619. - renderMaps:(WW3DCamera *)camera  startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime usingStream:(NXStream *)ns
  620. {
  621.   return self;
  622. }
  623.  
  624. - renderMaps:(WW3DCamera *)camera usingStream:(NXStream *)ns
  625. {
  626.   RtFloat  shutterOpenTime = [camera shutterOpenTime],
  627.            shutterCloseTime = [camera shutterCloseTime];
  628.  
  629.  
  630.   return [self renderMaps:camera startingAt:shutterOpenTime endingAt:shutterCloseTime usingStream:(NXStream *)ns];
  631. }
  632.  
  633. - renderMaps:(WW3DCamera *)camera  startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  634. {
  635.   return self;
  636. }
  637.  
  638. - renderMaps:(WW3DCamera *)camera
  639. {
  640.   RtFloat  shutterOpenTime = [camera shutterOpenTime],
  641.            shutterCloseTime = [camera shutterCloseTime];
  642.  
  643.  
  644.   return [self renderMaps:camera startingAt:shutterOpenTime endingAt:shutterCloseTime];
  645. }
  646.  
  647. - renderSelfAsBox:(WW3DCamera *)camera  startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  648. {
  649.   if ([self hasBoundingBox])
  650.   {  // if I have a bounding box, don't render myself
  651.   }
  652.   else
  653.   {  // otherwise, render myself like normal
  654.      [self renderSelf:camera  startingAt:shutterOpenTime endingAt:shutterCloseTime];
  655.   }
  656.  
  657.   // the idea here is that if it has a boundingBox, we don't want to
  658.   // render it (since it has some real geometry, and the whole point of
  659.   // this routine is to avoid drawing geometry).  If, on the other hand, it
  660.   // doesn't have a bounding box, it (at most) just transforms the current
  661.   // transformation matrix.
  662.  
  663.   return self;
  664. }
  665.  
  666.  
  667. - renderSelf:(WW3DCamera *)camera  startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  668. {
  669.   char comment[256];
  670.  
  671.   sprintf(comment, "RIBCommand subclass %s called", [self name]);
  672.   RiArchiveRecord("comment", comment);
  673.   return self;
  674. }
  675.  
  676. - renderSelf:(WW3DCamera *)camera
  677. {
  678.   RtFloat  shutterOpenTime = [camera shutterOpenTime],
  679.            shutterCloseTime = [camera shutterCloseTime];
  680.  
  681.  
  682.   return [self renderSelf:camera startingAt:shutterOpenTime endingAt:shutterCloseTime];
  683. }
  684.  
  685. - preRenderSelf:(WW3DCamera *)camera  startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  686. {
  687.   RiArchiveRecord("comment", "RIBCommand called"); 
  688.   return self;
  689. }
  690.  
  691. - preRenderSelf:(WW3DCamera *)camera
  692. {
  693.   RtFloat  shutterOpenTime = [camera shutterOpenTime],
  694.            shutterCloseTime = [camera shutterCloseTime];
  695.  
  696.  
  697.   return [self renderSelf:camera startingAt:shutterOpenTime endingAt:shutterCloseTime];
  698. }
  699.  
  700. - transformCTM:(WW3DAttributeState *)attributeState startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime { return self; }
  701.  
  702. - (BOOL)isMotionBlurrable { return NO; }
  703.  
  704. - (BOOL)isCompoundCommand { return NO; }
  705.  
  706. - (BOOL)isLerpable { return NO; }
  707.  
  708. - (const char *)getInspectorClassName { return "RIBCommandIBInspector"; }
  709.  
  710. // WavesWorld archiving:
  711. // writeEve:(NXStream *)stream
  712. // writeScene:(NXStream *)stream
  713.  
  714. - writeEve:(NXStream *)stream atTabLevel:(int)tab
  715. {
  716.    int  i;
  717.  
  718.  
  719.    for (i = 0; i < tab; i++)
  720.    {  NXPrintf(stream, "\t");
  721.    }
  722.    NXPrintf(stream, "#RIBCommand %s called;", [self name]); 
  723.    return self;
  724. }
  725.  
  726. - writeScene:(NXStream *)stream atTabLevel:(int)tab
  727. {
  728.    return [self writeEve:stream atTabLevel:tab];
  729. }
  730.  
  731.  
  732. - write3DTextScene:(NXStream *)stream atTabLevel:(int)tab index:(int)index time:(float)time until:(float)lastTime
  733. {
  734.    int  i;
  735.  
  736.  
  737.    for (i = 0; i < tab; i++)
  738.    {  NXPrintf(stream, "\t");
  739.    }
  740.  
  741.    NXPrintf(stream, "set __text__(color%s) {1 1 1}\n", [[self class] name]);
  742.    NXPrintf(stream, "startShape %s; EveCmd {Color $__text__(color%s)}; ", [[self class] name], [[self class] name]);
  743.    // need tab
  744.    // need index (position in current list)
  745.    NXPrintf(stream, 
  746.         "EveCmd {Translate [expr { %d * $__text__(tabLength)}] [expr {$__text__(spacingFactor) * %d * $__text__(spacing) * $__text__(fontSize)}] 0 };\n", 
  747.             tab, index); 
  748.    for (i = 0; i < tab; i++)
  749.    {  NXPrintf(stream, "\t");
  750.    }
  751.    NXPrintf(stream, "  EveCmd {WW3DText $__text__(fontName) $__text__(fontSize) {");
  752.    [self writeEve:stream atTabLevel:tab];
  753.    NXPrintf(stream, "} left;}\n");
  754.   NXPrintf(stream, "endShape;\n");
  755.  
  756.   return self;
  757. }
  758.  
  759.  
  760. // this is a routine for subclasses to call when archiving themselves to an Inventor file...
  761. - writeParameterListForInventor:(NXStream *)stream atTabLevel:(int)tab
  762. {
  763.   int  i, j, k;
  764.  
  765.   
  766.    if (!n)
  767.    {  return nil;
  768.    }
  769.  
  770.    // so what's the best way to do this?  basically, since Inventor is
  771.    // pretty restricted in what it can support, we need to examine each
  772.    // token, see if it's one that Inventor supports, and if so, spit it out.
  773.    
  774.    // so what does Inventor support?
  775.    // basically, we want to be able to map the following:
  776.    // "P" -> Coordinate3
  777.    // "Pw" -> Coordinate4
  778.    // "N" -> Normal
  779.    // "st" -> TextureCoordinate2
  780.    // "s" "t" -> need to scan for both and generate TextureCoordinate2
  781.  
  782.    for (i = 0; i < n; i++)
  783.    {  
  784.       if (!strcmp("P", tokens[i]))
  785.       {  
  786.          // I can't think of any reason that there wouldn't at least
  787.          // two points, which the following assumes, but if there's 
  788.          // not, I should catch it and do the right thing, sigh...
  789.          if (printfNVector[i] < 6)
  790.          {  for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  791.             NXPrintf(stream, "# less than 2 points - unable to convert RenderMan P token to Inventor Coordinate3 node!\n");
  792.             break;
  793.          }
  794.  
  795.          j = 0;
  796.  
  797.          // write node name and first point
  798.          for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  799.          NXPrintf(stream, "Coordinate3 {\n");
  800.      for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  801.          NXPrintf(stream, "point [%f ", *((RtFloat *)(parms[i]) + j)); j++;
  802.          NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  803.          NXPrintf(stream, "%f,\n", *((RtFloat *)(parms[i]) + j)); j++;
  804.  
  805.          // loop over the points, writing them out
  806.          while (j < (printfNVector[i] - 3))
  807.      {  for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  808.         NXPrintf(stream, "       %f ", *((RtFloat *)(parms[i]) + j)); j++;
  809.         NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  810.         NXPrintf(stream, "%f,\n", *((RtFloat *)(parms[i]) + j)); j++;
  811.       }
  812.  
  813.          // finish up with the last one
  814.      for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  815.      NXPrintf(stream, "       %f ", *((RtFloat *)(parms[i]) + j)); j++;
  816.      NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  817.      NXPrintf(stream, "%f]\n", *((RtFloat *)(parms[i]) + j)); j++;
  818.  
  819.          // okay, cap it off and move on
  820.          for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  821.      NXPrintf(stream, "}\n", *((RtFloat *)(parms[i]) + j)); j++;
  822.      break;
  823.       }
  824.  
  825.       if (!strcmp("Pw", tokens[i]))
  826.       {  
  827.          // I can't think of any reason that there wouldn't at least
  828.          // two points, which the following assumes, but if there's 
  829.          // not, I should catch it and do the right thing, sigh...
  830.          if (printfNVector[i] < 8)
  831.          {  for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  832.             NXPrintf(stream, "# less than 2 points - unable to convert RenderMan Pw token to Inventor Coordinate4 node!\n");
  833.             break;
  834.          }
  835.  
  836.          j = 0;
  837.  
  838.          // write node name and first point
  839.          for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  840.          NXPrintf(stream, "Coordinate4 {\n");
  841.      for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  842.          NXPrintf(stream, "point [%f ", *((RtFloat *)(parms[i]) + j)); j++;
  843.          NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  844.          NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  845.          NXPrintf(stream, "%f,\n", *((RtFloat *)(parms[i]) + j)); j++;
  846.  
  847.          // loop over the points, writing them out
  848.          while (j < (printfNVector[i] - 4))
  849.      {  for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  850.         NXPrintf(stream, "       %f ", *((RtFloat *)(parms[i]) + j)); j++;
  851.         NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  852.         NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  853.         NXPrintf(stream, "%f,\n", *((RtFloat *)(parms[i]) + j)); j++;
  854.       }
  855.  
  856.          // finish up with the last one
  857.      for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  858.      NXPrintf(stream, "       %f ", *((RtFloat *)(parms[i]) + j)); j++;
  859.      NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  860.      NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j)); j++;
  861.      NXPrintf(stream, "%f]\n", *((RtFloat *)(parms[i]) + j)); j++;
  862.  
  863.          // okay, cap it off and move on
  864.          for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  865.      NXPrintf(stream, "}\n", *((RtFloat *)(parms[i]) + j)); j++;
  866.      break;
  867.      }
  868.    }
  869.    return self;
  870. }
  871.  
  872. - writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
  873. {
  874.    int  i;
  875.  
  876.  
  877.    for (i = 0; i < tab; i++)
  878.    {  NXPrintf(stream, "\t");
  879.    }
  880.    NXPrintf(stream, "# RIBCommand %s called;", [[self class] name]); 
  881.    return self;
  882.  
  883. }
  884.  
  885.  
  886. // this is a routine for subclasses to call when archiving themselves to an eve file or a scene...
  887. - writeParameterList:(NXStream *)stream
  888. {
  889.   int  i, j;
  890.  
  891.   
  892.    if (!n)
  893.    {  NXPrintf(stream, ";");
  894.       return nil;
  895.    }
  896.    for (i = 0; i < n; i++)
  897.    {  NXPrintf(stream, "{%s} ", tokens[i]);
  898.       switch (printfTypeVector[i])
  899.       {  case WW_FLOAT:   NXPrintf(stream, "{ ");
  900.                           for (j = 0; j < printfNVector[i]; j++)
  901.                       {  NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j));
  902.               }
  903.                       NXPrintf(stream, "} ");  
  904.                           break;
  905.          case WW_COLOR:   NXPrintf(stream, "{ ");
  906.                           for (j = 0; j < printfNVector[i]; j++)
  907.                        {  NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j));
  908.               }
  909.                       NXPrintf(stream, "} ");  
  910.                           break;
  911.          case WW_POINT:   NXPrintf(stream, "{ ");
  912.                           for (j = 0; j < printfNVector[i]; j++)
  913.                        {  NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j));
  914.               }
  915.                       NXPrintf(stream, "} ");  
  916.                           break;
  917.          case WW_INT:     NXPrintf(stream, "{ ");
  918.                           for (j = 0; j < printfNVector[i]; j++)
  919.                        {  NXPrintf(stream, "%d ", *((int *)(parms[i]) + j));
  920.               }
  921.                       NXPrintf(stream, "} ");  
  922.                           break;
  923.          case WW_STRING:  for (j = 0; j < printfNVector[i]; j++)
  924.                        {  NXPrintf(stream, "{%s} ", *((char **)(parms[i]) + j));
  925.               }
  926.                           break;
  927.       }      
  928.    }
  929.    NXPrintf(stream, ";");
  930.    return self;
  931. }
  932.  
  933.  
  934.  
  935. // NeXTSTEP archiving:
  936.  
  937. #define typeVector "i"
  938. #define typeValues &n
  939.  
  940. - read:(NXTypedStream*)stream 
  941. {
  942.   int version, i, arrayLength;
  943.  
  944.  
  945.   [super read:stream];
  946.  
  947.   version = NXTypedStreamClassVersion(stream,"RIBCommand");
  948.   if (version == 0) NXReadTypes(stream,"i",&version), version=1;
  949.   if (version == 1)
  950.   {  NXReadArray(stream, "f", 6, boundingBox);
  951.      NXReadTypes(stream, typeVector, typeValues);
  952.      myShape = NXReadObject(stream);
  953. NX_DURING
  954.      if (n)
  955.      {  if ([self zone])
  956.         {  tokens = (char **)NXZoneMalloc([self zone], sizeof(char *) * n);
  957.            archiveVector = (char **)NXZoneMalloc([self zone], sizeof(char *) * n);
  958.            parms = (RtPointer *)NXZoneMalloc([self zone], sizeof(RtPointer) * n);
  959.         }
  960.         else
  961.         {  tokens = (char **)malloc(sizeof(char *) * n);
  962.            archiveVector = (char **)malloc(sizeof(char *) * n);
  963.            parms = (RtPointer *)malloc(sizeof(RtPointer) * n);
  964.         }
  965.         for (i = 0; i < n; i++)
  966.         {  //NXLogError("RIBCommand: attempting to read token[%d] and archiveVector[%d] of %d...\n", i, i, n);
  967.            NXReadTypes(stream, "**", &(tokens[i]), &(archiveVector[i]));
  968.            //NXLogError("RIBCommand: read: tokens[%d] == <%s> archiveVector[%d] == <%s>\n", 
  969.            //           i, tokens[i], i, archiveVector[i]);
  970.            //NXLogError("RIBCommand: got 'em!\n");
  971.            //NXLogError("RIBCommand: attempting to read parm[%d] using archiveVector <%s>...\n", i, archiveVector[i]);
  972.  
  973.            // archiveVector is of the form [%df] or [%di]
  974.            // therefore, we can check the second to last character, and key off that
  975.            if (*(archiveVector[i] + strlen(archiveVector[i]) - 2) == 'f')
  976.            {  //  it's a float
  977.               sscanf(archiveVector[i], "[%df]", &arrayLength);
  978.               if ([self zone])
  979.               {  parms[i] = (float *)NXZoneMalloc([self zone], sizeof(float) * arrayLength);
  980.               }
  981.               else
  982.               {  parms[i] = (float *)malloc(sizeof(float) * arrayLength);
  983.               }
  984.               if (!parms[i]) 
  985.               {  NXLogError("Yikes! Unable to allocate %d bytes in read: for %s\n", 
  986.                             (sizeof(float) * arrayLength), [[self class] name]);
  987.               }
  988.               else
  989.               {  NXReadArray(stream, "f", arrayLength, parms[i]);
  990.               }
  991.            }
  992.            else
  993.            {  if (*(archiveVector[i] + strlen(archiveVector[i]) - 2) == 'i')
  994.               {  //  it's an integer
  995.                  sscanf(archiveVector[i], "[%di]", &arrayLength);
  996.                  if ([self zone])
  997.                  {  parms[i] = (int *)NXZoneMalloc([self zone], sizeof(int) * arrayLength);
  998.           }
  999.                  else
  1000.                  {  parms[i] = (int *)malloc(sizeof(int) * arrayLength);
  1001.           }
  1002.                  if (!parms[i]) 
  1003.                  {  NXLogError("Yikes! Unable to allocate %d bytes in read: for %s\n", 
  1004.                                (sizeof(int) * arrayLength), [[self class] name]);
  1005.                  }
  1006.                  else
  1007.                  {  NXReadArray(stream, "i", arrayLength, parms[i]);
  1008.                  }
  1009.            }
  1010.               else
  1011.               {  NXLogError("unable to decipher archiveVector[%d] == %s - didn't read the corresponding data\n", i, archiveVector[i]);
  1012.               }
  1013.            }
  1014.            //NXLogError("RIBCommand: got it!\n");
  1015.         }
  1016.      } 
  1017. NX_HANDLER
  1018.    NXLogError("in read:'ing the parameter list for RIBCommand, the subclass %s, exception [%d] raised where i == %d (n == %d).\n", 
  1019.                  [[self class] name], NXLocalHandler.code, i, n);
  1020.    return nil;
  1021. NX_ENDHANDLER
  1022.    }
  1023.  
  1024.   return self; 
  1025. }
  1026.  
  1027. - write:(NXTypedStream*)stream 
  1028. {
  1029.   int  i, arrayLength;
  1030.  
  1031.     
  1032.   [super write:stream];
  1033.  
  1034.   NXWriteArray(stream, "f", 6, boundingBox);
  1035.   NXWriteTypes(stream,typeVector, typeValues);
  1036.   NXWriteObjectReference(stream, myShape);
  1037. NX_DURING
  1038.   for (i = 0; i < n; i++)
  1039.   {  //NXLogError("RIBCommand: write: tokens[%d] == <%s> archiveVector[%d] == <%s>\n", 
  1040.      //           i, tokens[i], i, archiveVector[i]);
  1041.      NXWriteTypes(stream, "**", &(tokens[i]), &(archiveVector[i]));
  1042.  
  1043.      // archiveVector is of the form [%df] or [%di]
  1044.      // therefore, we can check the second to last character, and key off that
  1045.      if (*(archiveVector[i] + strlen(archiveVector[i]) - 2) == 'f')
  1046.      {  //  it's a float
  1047.         sscanf(archiveVector[i], "[%df]", &arrayLength);
  1048.         NXWriteArray(stream, "f", arrayLength, parms[i]);
  1049.      }
  1050.      else
  1051.      {  if (*(archiveVector[i] + strlen(archiveVector[i]) - 2) == 'i')
  1052.         {  //  it's an integer
  1053.            sscanf(archiveVector[i], "[%di]", &arrayLength);
  1054.            NXWriteArray(stream, "i", arrayLength, parms[i]);
  1055.         }
  1056.         else
  1057.         {  NXLogError("unable to decipher archiveVector[%d] == %s - didn't write the corresponding data\n", i, archiveVector[i]);
  1058.         }
  1059.      }
  1060.   }
  1061. NX_HANDLER
  1062.    NXLogError("in write:'ing the parameter list for RIBCommand, the subclass %s, exception [%d] raised where i == %d (n == %d).\n", 
  1063.                  [[self class] name], NXLocalHandler.code, i, n);
  1064.    return nil;
  1065. NX_ENDHANDLER
  1066.  
  1067.   return self;
  1068. }
  1069.  
  1070.  
  1071. // boy, this is dumb... This is to get around the stupid warnings from the compiler - ask wave for details
  1072. - class { return [super class]; }
  1073.  
  1074. @end
  1075.